<?php

abstract class Controller
{
	protected $controller_name;
	protected $action_name;
	protected $application;
	protected $request;
	protected $response;
	protected $session;
	protected $db_manager;
	protected $auth_actions = array();
	protected $auth = false;
	
	
	
	public function __construct($application)
	{
		$this->controller_name = strtolower(substr(get_class($this), 0, -10));
		
		$this->application	= $application;
		$this->request		= $application->getRequest();
		$this->response		= $application->getResponse();
		$this->session		= $application->getSession();
		$this->db_manager	= $application->getDbManager();
		$this->auth			= $this->Ifauth();
	}
	
	
	
	public function run($action, $params = array())
	{
		$this->action_name =$action;
		
		$action_method = $action . 'Action';
		if (!method_exists($this, $action_method)) {
			$this->forword404();
		}
		
		if ($this->needAuthentication($action) && !$this->session->isAuthenticated()) {
			throw new UnauthorizedActionException();
		}
		
		$content = $this->$action_method($params);
		
		return $content;
	}
	
	
	
	protected function render($variables = array(), $template = null, $layout = 'layout')
	{
		$defaults = array(
			'request'	=> $this->request,
			'base_url'	=> $this->request->getBaseUrl(),
			'session'	=> $this->session
			);
			
		$view = new View($this->application->getViewDir(), $defaults);
		
		if (is_null($template)) {
			$template = $this->action_name;
		}
		
		$path = $this->controller_name . '/' . $template;
		if ($layout !== false) {
			if (isset($variables['css'])) $view->setLayoutvar('css', $variables['css']);
			if (isset($variables['title'])) $view->setLayoutvar('title', $variables['title']);
			if (isset($variables['auth'])) $view->setLayoutvar('auth', $variables['auth']);
			if (isset($variables['js'])) $view->setLayoutvar('js', $variables['js']);
			if (isset($variables['path_info'])) $view->setLayoutvar('path_info', $variables['path_info']);
		}
		
		return $view->render($path, $variables, $layout);
	}
	
	
	
	protected function forword404()
	{
		throw new HttpNotFoundException('Forworded 404 page from http://' . APP_DOMAIN . '/' . $this->controller_name . '/' . $this->action_name);
	}
	
	
	
	protected function redirect($url)
	{
		if (!preg_match('#https?://#', $url)) {
			$protocol = $this->request->isSsl() ? 'https://' : 'http://';
			$host = $this->request->getHost();
			$base_url = $this->request->getBaseUrl();
			
			$url = $protocol . $host . $base_url . $url;
		}
		
		$this->response->setStatusCode(302, 'Found');
		$this->response->setHttpHeader('Location', $url);
	}
	
	
	
	protected function generateCsrfToken($form_name)
	{
		$key = 'csrf_tokens/' . $form_name;
		$tokens = $this->session->get($key, array());
		if (count($tokens) >= 10) {
			array_shift($tokens);
		}
		
		$token = sha1($form_name . session_id() . microtime());
		$tokens[] = $token;
		
		$this->session->set($key, $tokens);
		
		return $token;
	}
	
	
	
	protected function checkCsrfToken($form_name, $token)
	{
		$key = 'csrf_tokens/' . $form_name;
		$tokens = $this->session->get($key, array());
		
		if (false !== ($pos = array_search($token, $tokens, true))) {
			unset($tokens[$pos]);
			$this->session->set($key, $tokens);
			
			return true;
		}
		
		return false;
	}
	
	
	
	protected function needAuthentication($action)
	{
		if ($this->auth_actions === true
			|| (is_array($this->auth_actions) && in_array($action, $this->auth_actions))) {
			return true;
		}
		
		return false;
	}



/*-----------------------------------------------------------*/



	public function ifAutoLoginKey()
	{
		if (!isset($_COOKIE['auto_login'])) {
			return false;
		}

		$key = $_COOKIE['auto_login'];
		$check_id = $this->db_manager->get('AutoLogin')->checkAutoLogin($key);
			
		if (is_null($check_id)) {
			return false;
		}

		$user_data = $this->db_manager->get('User')->fetchById($check_id);
		if (is_null($user_data)) {
			return false;
		}

		$this->session->setAuthenticated(true);
		$this->session->set('user',$user_data);

		return true;
	}



	public function ifAuth()
	{
		if (!$this->session->isAuthenticated()) {
			if (!$this->ifAutoLoginKey()) {
				return false;
			}
		}

		$user_data = $this->session->get('user');
		
		if (isset($_REQUEST['auto_login'])) {
			$this->db_manager->get('AutoLogin')->deleteAutoLogin($user_data['id']);
			$this->db_manager->get('AutoLogin')->makeAutoLogin($user_data['id']);
		}
		
		return true;
	}
}